/*    file: H265Packager.cpp
 *    desc:
 * 
 * created: 2014-07-21 15:24:43
 *  author: zhengchuanjiang
 * company: 
 */

#include "stdafx.h"
#include "H265Packager.h"
#include "RtpHeader.h"


H265Packager::H265Packager():
    m_file()
{

}

H265Packager::~H265Packager()
{
    close();
}

bool H265Packager::open(const char* filename)
{
    fopen_s(&m_file, filename, "wb");
    return (m_file != NULL);
}

bool H265Packager::isOpen()
{
    return (m_file != NULL);
}

void H265Packager::close()
{
    if (m_file)
    {
        fclose(m_file);
        m_file = NULL;
    }
}


static unsigned char s_startCode[] = { 0, 0, 0, 1};

void H265Packager::write(BYTE* ptr, UINT16 size)
{
	if (!isOpen())
	{
		return;
	}

	RTP_FIXED_HEADER* rtpHeader = (RTP_FIXED_HEADER*)ptr;

	if (size <= sizeof(RTP_FIXED_HEADER))
	{
		return;
	}


	BYTE* data = ptr + sizeof(RTP_FIXED_HEADER);
	size_t  length = size - sizeof(RTP_FIXED_HEADER);

    if (rtpHeader->extension)
    {
        RTP_EXT_HEADER* extHeader = (RTP_EXT_HEADER*)data;
        int extLength = ntohs(extHeader->length);

        data += 4 + extLength * 4;
        length -= 4 + extLength * 4;

        if (length <= 0)
        {
            return;
        }
    }

	bool isFU = ((data[0] >> 1) & 49) == 49;
	uint8_t naluType = (data[0] & 0x7E) >> 1;
	bool fullPacket = rtpHeader->marker;
	bool keyFrame = false;

	if (isFU)
	{
		naluType = data[2] & 0x1F;

		uint8_t hdr[2] = { 0, data[1] };
		hdr[0] = (data[0] & 0x81) | ((naluType << 1) & 0x7E);

		unsigned char startBit = data[2] & 0x80;
		unsigned char endBit = data[2] & 0x40;

		if (startBit)
		{
			m_buffer.clear();
			m_buffer.write(s_startCode, sizeof(s_startCode));
			m_buffer.write(hdr, sizeof(hdr));
		}
		else if (m_buffer.empty())
		{
			m_buffer.clear();
			m_buffer.write(s_startCode, sizeof(s_startCode));
			m_buffer.write(hdr, sizeof(hdr));
		}

		data += 3;
		length -= 3;

		m_buffer.write(data, length);

		if (endBit)
		{
			fullPacket = true;

			naluType = (m_buffer.data()[3 + 1] & 0x7E) >> 1;

			keyFrame = (naluType == 32 || naluType == 33 || naluType == 34
				//|| naluType == 39
				|| naluType == 19 || naluType == 20 || naluType == 21);
		}
	}
	else
	{
		if (m_buffer.empty())
		{
			m_buffer.write(s_startCode, sizeof(s_startCode));
		}
		else
		{
			//size_t len = m_buffer.length();
		}

		m_buffer.write(data, length);
		fullPacket = true;
		keyFrame = (naluType == 32 || naluType == 33 || naluType == 34
			//|| naluType == 39
			|| naluType == 19 || naluType == 20 || naluType == 21);
	}

	if (fullPacket)
	{
		fwrite(m_buffer.data(), 1, m_buffer.length(), m_file);
		m_buffer.clear();
	}
}

/*

void H265Packager::write(BYTE* ptr, UINT16 size)
{
    if (!isOpen())
    {
        return;
    }

	RTP_FIXED_HEADER* rtpHeader = (RTP_FIXED_HEADER*)ptr;

	if (size <= sizeof(RTP_FIXED_HEADER))
	{
		return;
	}

    BYTE* data = ptr + sizeof(RTP_FIXED_HEADER);
    size_t  length = size - sizeof(RTP_FIXED_HEADER);

	bool isFU = ((data[0] >> 1) & 49) == 49;
	uint8_t naluType = (data[0] & 0x7E) >> 1;
	bool fullPacket = rtpHeader->marker;
	bool keyFrame = false;
    
	if (isFU)
	{
		naluType = data[2] & 0x1F;

		uint8_t hdr[2] = { 0, data[1] };
		hdr[0] = (data[0] & 0x81) | ((naluType << 1) & 0x7E);

		unsigned char startBit = data[2] & 0x80;
		unsigned char endBit = data[2] & 0x40;

		if (startBit)
		{
			m_buffer.clear();
			m_buffer.write(s_startCode, sizeof(s_startCode));
			m_buffer.write(hdr, sizeof(hdr));
		}
		else if (m_buffer.empty())
		{
			m_buffer.clear();
			m_buffer.write(s_startCode, sizeof(s_startCode));
			m_buffer.write(hdr, sizeof(hdr));
		}

		data += 3;
		length -= 3;

		m_buffer.write(data, length);

		if (endBit)
		{
			fullPacket = true;
		}
	}
	else
	{
		if (m_buffer.empty())
		{
			m_buffer.write(s_startCode, sizeof(s_startCode));
		}
		else
		{
			//size_t len = m_joinBuffer.length();
		}

		m_buffer.write(data, length);
		fullPacket = true;
	}

    if (fullPacket)
    {
        fwrite(m_buffer.data(), 1, m_buffer.size(), m_file);
		fflush(m_file);

        m_buffer.clear();
    }
    
}
*/